package com.duojuhe.coremodule.system.service.impl;


import com.duojuhe.cache.SystemDictCache;
import com.duojuhe.common.bean.UserTokenInfoVo;
import com.duojuhe.common.constant.SystemConstants;
import com.duojuhe.common.enums.SystemEnum;
import com.duojuhe.common.exception.base.DuoJuHeException;
import com.duojuhe.common.result.ErrorCodes;
import com.duojuhe.common.result.PageResult;
import com.duojuhe.common.result.ServiceResult;
import com.duojuhe.common.utils.idgenerator.UUIDUtils;
import com.duojuhe.common.utils.page.PageHelperUtil;
import com.duojuhe.common.utils.thread.ThreadUtils;
import com.duojuhe.coremodule.BaseService;
import com.duojuhe.coremodule.system.entity.SystemDict;
import com.duojuhe.coremodule.system.mapper.SystemDictMapper;
import com.duojuhe.coremodule.system.pojo.dto.dict.*;
import com.duojuhe.coremodule.system.service.SystemDictService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;
import java.util.Map;


@Slf4j
@Service
public class SystemDictServiceImpl extends BaseService implements SystemDictService {
    @Resource
    private SystemDictCache systemDictCache;
    @Resource
    private SystemDictMapper systemDictMapper;

    /**
     * 项目启动时，初始数据字典
     */
    @PostConstruct
    public void initSystemDictToCache() {
        log.info("=====初始数据字典到缓存中开始=====");
        loadingSystemDictCache();
        log.info("=====初始数据字典到缓存中结束=====");
    }

    /**
     * 根据主键查询
     * @param req
     * @return
     */
    @Override
    public ServiceResult<QuerySystemDictRes> querySystemDictResByDictId(SystemDictIdReq req) {
        String dictId = req.getDictId();
        QuerySystemDictRes res = systemDictMapper.querySystemDictResByDictId(dictId);
        setHandleSystemDictDictNameColor(res);
        return ServiceResult.ok(res);
    }


    /**
     * 查询一级数据字典
     * @param req
     * @return
     */
    @Override
    public ServiceResult<PageResult<List<QueryOneLevelSystemDictPageRes>>> queryOneLevelSystemDictPageResList(QueryOneLevelSystemDictPageReq req) {
        PageHelperUtil.orderByAndStartPage(req, "sort desc,createTime desc,dictId desc");
        List<QueryOneLevelSystemDictPageRes> list = systemDictMapper.queryOneLevelSystemDictPageResList(req);
        list.forEach(this::setHandleSystemDictDictNameColor);
        return PageHelperUtil.returnServiceResult(req,list);
    }

    /**
     * 查询子级数据字典
     * @param req
     * @return
     */
    @Override
    public ServiceResult<PageResult<List<QueryChildrenSystemDictPageRes>>> queryChildrenSystemDictPageResList(QueryChildrenSystemDictPageReq req) {
        PageHelperUtil.orderByAndStartPage(req, "sort desc,createTime desc,dictId desc");
        List<QueryChildrenSystemDictPageRes> list = systemDictMapper.queryChildrenSystemDictPageResList(req);
        list.forEach(this::setHandleSystemDictDictNameColor);
        return PageHelperUtil.returnServiceResult(req,list);
    }

    /**
     * 保存数据字典
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceResult saveSystemDict(SaveSystemDictReq req) {
        //父级id，默认-1是一级字典
        String parentId = SystemConstants.UNKNOWN_ID;
        //字典类型
        String dictTypeCode = SystemEnum.DICT_TYPE.BUSINESS_DICT.getKey();
        //查询父级
        if (!parentId.equals(req.getParentId())){
            SystemDict parentDict = systemDictMapper.selectByPrimaryKey(req.getParentId());
            if (parentDict == null) {
                return ServiceResult.fail(ErrorCodes.PARENT_PARAM_ERROR);
            }
            if (SystemEnum.DICT_TYPE.SYSTEM_DICT.getKey().equals(parentDict.getDictTypeCode())) {
                return ServiceResult.fail(ErrorCodes.DICT_PARENT_DICT_IS_BUILT_IN_ERROR);
            }
            //父级id
            parentId = parentDict.getDictId();
            //父级字典类型
            dictTypeCode = StringUtils.isNotBlank(parentDict.getDictTypeCode())?parentDict.getDictTypeCode():dictTypeCode;
        }
        //字典code
        String dictCode = req.getDictCode().toUpperCase();
        //检查数据字典编码是否存在
        checkSystemDictCodeExist(dictCode);
        //当前登录用户
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //当前时间
        Date date = new Date();
        //数据字典ID
        String dictId = UUIDUtils.getUUID32();
        //构建数据字典对象
        SystemDict dict = new SystemDict();
        dict.setDictId(dictId);
        dict.setParentId(parentId);
        dict.setDictName(req.getDictName());
        dict.setDictCode(dictCode);
        dict.setRemark(req.getRemark());
        dict.setStatusCode(req.getStatusCode());
        dict.setSort(req.getSort());
        dict.setCreateTime(date);
        dict.setDictColor(req.getDictColor());
        dict.setCreateUserId(userTokenInfoVo.getUserId());
        dict.setUpdateTime(date);
        dict.setDictTypeCode(dictTypeCode);
        dict.setUpdateUserId(userTokenInfoVo.getUserId());
        int row = systemDictMapper.insertSelective(dict);
        if (row>0){
            //更新缓存
            systemDictCache.putSystemDictCache(dict);
        }
        return ServiceResult.ok(dictId);
    }


    /**
     * 修改数据字典
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceResult updateSystemDict(UpdateSystemDictReq req) {
        SystemDict dict = systemDictMapper.selectByPrimaryKey(req.getDictId());
        if (dict == null) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //当前登录用户
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //当前时间
        Date date = new Date();
        //更新返回值
        int row = 0;
        if (SystemEnum.DICT_TYPE.SYSTEM_DICT.getKey().equals(dict.getDictTypeCode())) {
            //系统内置字典可修改，名称，备注，排序，颜色
            dict.setDictName(req.getDictName());
            dict.setRemark(req.getRemark());
            dict.setSort(req.getSort());
            dict.setDictColor(req.getDictColor());
            dict.setUpdateTime(date);
            dict.setUpdateUserId(userTokenInfoVo.getUserId());
            //更新数据库
            row = systemDictMapper.updateByPrimaryKeySelective(dict);
        }else{
            //数据字典code
            String dictCode = req.getDictCode().toUpperCase();
            if (!dict.getDictCode().equals(dictCode)) {
                //检查数据字典编码是否存在
                checkSystemDictCodeExist(dictCode);
                //删除之前的数据字典
                systemDictCache.deleteSystemDictByDictCode(dict.getDictCode());
            }
            dict.setDictName(req.getDictName());
            dict.setDictCode(dictCode);
            dict.setRemark(req.getRemark());
            dict.setStatusCode(req.getStatusCode());
            dict.setSort(req.getSort());
            dict.setDictColor(req.getDictColor());
            dict.setUpdateTime(date);
            dict.setUpdateUserId(userTokenInfoVo.getUserId());
            //更新数据库
            row = systemDictMapper.updateByPrimaryKeySelective(dict);
        }
        if (row>0){
            //更新缓存
            systemDictCache.putSystemDictCache(dict);
        }
        return ServiceResult.ok(req.getDictId());
    }


    /**
     * 删除数据字典
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceResult deleteSystemDictByDictId(SystemDictIdReq req) {
        //字典id
        String dictId = req.getDictId();
        //查询对象
        SystemDict systemDict = systemDictMapper.selectByPrimaryKey(dictId);
        if (systemDict == null) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        if (SystemEnum.DICT_TYPE.SYSTEM_DICT.getKey().equals(systemDict.getDictTypeCode())) {
            return ServiceResult.fail(ErrorCodes.DICT_BUILT_IN_NOT_DELETE);
        }
        //检查是否存在下级
        checkSystemDictChildren(systemDict.getDictId());
        //删除数据库
        int row = systemDictMapper.deleteByPrimaryKey(dictId);
        if (row>0){
            //删除缓存
            systemDictCache.deleteSystemDictByDictCode(systemDict.getDictCode());
        }
        return ServiceResult.ok(dictId);
    }

    /**
     * 加载数据字典缓存数据
     */
    @Override
    public void loadingSystemDictCache() {
        //先清除
        systemDictCache.clearSystemDictCache();
        //再插入
        systemDictCache.putSystemDictCache(systemDictMapper.selectAll());
    }


    /**
     * 清空数据字典缓存数据
     */
    @Override
    public void clearSystemDictCache() {
        systemDictCache.clearSystemDictCache();
    }

    /**
     * 重置数据字典缓存数据
     */
    @Override
    public ServiceResult resetSystemDictCache() {
        ThreadUtils.execute(() -> {
            try {
                //先清空之前的
                clearSystemDictCache();
                //加载新的
                loadingSystemDictCache();
            }catch (Exception e){
                log.error("重置数据字典缓存出现异常",e);
            }
        });
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }

    /**
     * 【根据code集合获取数据字典】根据数据字典父级code编码获取数据字典
     * @param req
     * @return
     */
    @Override
    public ServiceResult<Map<String, List<SelectChildrenDictRes>>> queryCommonDictListByParentDictCodeList(SystemDictCodeListReq req) {
        return ServiceResult.ok(systemDictCache.queryChildrenSystemDictListByParentDictCode(req.getDictCodeList()));
    }




    /*====================================私有方法beg================================================**/

    /**
     * 【私有方法，辅助其他接口方法使用】 查找该节点下面是否存在子节点
     */
    private void checkSystemDictChildren(String parentId) {
        if (StringUtils.isBlank(parentId)){
            throw new DuoJuHeException(ErrorCodes.EXIST_CHILDREN_DICT_NOT_DELETE);
        }
        Example example = new Example(SystemDict.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("parentId", parentId);
        if (systemDictMapper.selectByExample(example).size() > 0) {
            throw new DuoJuHeException(ErrorCodes.EXIST_CHILDREN_DICT_NOT_DELETE);
        }
    }


    /**
     * 【私有方法，辅助其他接口方法使用】 查询数据字典code编码是否已经存在
     */
    private void checkSystemDictCodeExist(String dictCode) {
        Example example = new Example(SystemDict.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("dictCode", dictCode);
        if(systemDictMapper.selectByExample(example).size()>0){
            throw new DuoJuHeException(ErrorCodes.DICT_CODE_EXIST);
        }
    }


    /**
     * 处理返回值的数据字典
     * @param res
     */
    private void setHandleSystemDictDictNameColor(HandleSystemDictDictNameColorRes res) {
        if (res==null){
            return;
        }
        SystemDict dictType = systemDictCache.getSystemDictByDictCode(res.getDictTypeCode());
        res.setDictTypeName(dictType.getDictName());
        res.setDictTypeColor(dictType.getDictColor());

        SystemDict dictStatus = systemDictCache.getSystemDictByDictCode(res.getStatusCode());
        res.setStatusName(dictStatus.getDictName());
        res.setStatusColor(dictStatus.getDictColor());
    }
    /*====================================私有方法end================================================**/
}
